package ch.ethz.fcl.metrobuzz.render.accessbility.view;

import java.awt.Color;
import java.util.List;

import org.lwjgl.opengl.GL11;

import ch.ethz.fcl.metrobuzz.MBContainer;
import ch.ethz.fcl.metrobuzz.applications.AccessibilityApp;
import ch.ethz.fcl.metrobuzz.data.MBData;
import ch.ethz.fcl.metrobuzz.data.accessibility.cost.MBEdgeCost;
import ch.ethz.fcl.metrobuzz.data.scene.basemap.Edge;
import ch.ethz.fcl.metrobuzz.render.accessbility.AccessibilityRender;
import ch.ethz.fcl.metrobuzz.render.techniques.colors.MBColorMap;
import ch.ethz.fcl.metrobuzz.render.techniques.projection.Projection;
import ch.ethz.fcl.metrobuzz.spatialindex.object2d.Point2D;
import ch.ethz.fcl.metrobuzz.spatialindex.object3d.Point3D;

public class RoadEfficiencyView {
	private MBContainer container;
	private AccessibilityRender acceRender;
	private MBColorMap colorMap;

	private float aveSpeed = 0;

	private boolean DEBUG = false;

	public RoadEfficiencyView(MBContainer container, AccessibilityRender render) {
		this.container = container;
		this.acceRender = render;
	}

	public void update() {
		colorMap = new MBColorMap(null, null, new String[] { "0", "1", "5" },
				new float[] { 0, 1, 5 });

		generateAveSpeed();
	}

	public void render() {
		renderRoadSpeed();
		renderColorMap();
	}

	private void generateAveSpeed() {
		float maxSpeed = 0, minSpeed = Float.MAX_VALUE;

		List<MBEdgeCost> edgeCostList = container.getData().getCost()
				.getRoadCosts();

		MBEdgeCost maxSpeedEdge = null;
		float distSum = 0;
		for (int i = 0; i < edgeCostList.size(); i++) {
			MBEdgeCost edgeCost = edgeCostList.get(i);

			float time = edgeCost.getCost(MBData.startTime);
			float dist = edgeCost.getEdge().distance();
			if (time == 0 || dist == 0)
				continue;

			float speed = dist / time;
			if (i == 0)
				aveSpeed = speed;
			else
				aveSpeed = (speed * dist + aveSpeed * distSum)
						/ (distSum + dist);

			distSum += dist;
			if (speed > maxSpeed)
				maxSpeedEdge = edgeCost;

			maxSpeed = Math.max(speed, maxSpeed);
			minSpeed = Math.min(speed, minSpeed);
		}
		if (maxSpeedEdge != null && DEBUG)
			System.out.println("max speed edge "
					+ maxSpeedEdge.getEdge().getId() + " dist "
					+ maxSpeedEdge.getEdge().distance() + " time cost "
					+ maxSpeedEdge.getCost(MBData.startTime));

		if (DEBUG)
			System.out.println("maxSpeed " + maxSpeed + " minSpeed " + minSpeed
					+ " aveSpeed " + aveSpeed);
	}

	private void renderColorMap() {
		Projection proj = container.getViewer().getProjection();

		int width = 250, height = 20;
		int screenWidth = AccessibilityApp.CANVAS_WIDTH;

		Point3D min = proj.getWorldCoord(new Point2D(screenWidth - width - 40,
				20), 0);

		Point3D max = proj.getWorldCoord(new Point2D(screenWidth - 40,
				20 + height), 0);

		colorMap.render(container, min.getX(), min.getY(), max.getX(),
				max.getY(), -90);
	}

	private void renderRoadSpeed() {
		List<MBEdgeCost> edgeCostList = container.getData().getCost()
				.getRoadCosts();

		GL11.glLineWidth(2.0f);
		GL11.glBegin(GL11.GL_LINES);

		for (MBEdgeCost edgeCost : edgeCostList) {
			float time = edgeCost.getCost(MBData.startTime);
			float dist = edgeCost.getEdge().distance();

			if (time == 0 || dist == 0)
				continue;

			float speed = dist / time;

			Color color = colorMap.getColor(speed / aveSpeed, 1, -90);
			int r = color.getRed(), g = color.getGreen(), b = color.getBlue();

			GL11.glColor4f(r / 255.0f, g / 255.0f, b / 255.0f, 0.7f);

			edgeCost.getEdge().render();
		}

		for (Edge e : container.getData().getPublicTransit().getTransitEdges())
			if (container.getData().getCost().getEdgeCost(e) == null) {
				float speed = aveSpeed;

				Color color = colorMap.getColor(speed / aveSpeed, 1, -90);
				int r = color.getRed(), g = color.getGreen(), b = color
						.getBlue();

				GL11.glColor4f(r / 255.0f, g / 255.0f, b / 255.0f, 0.7f);

				e.render();
			}

		GL11.glEnd();
	}

	public float getAveSpeed() {
		return aveSpeed;
	}

	public AccessibilityRender getAcceRender() {
		return acceRender;
	}
}
